// GTY


#include "UI/WidgetController/OverlayWidgetController.h"

#include "AuraGameplayTags.h"
#include "AbilitySystem/AuraAbilitySystemComponent.h"
#include "AbilitySystem/AuraAttributeSet.h"
#include "AbilitySystem/Data/AbilityInfo.h"
#include "AbilitySystem/Data/LeveUpInfo.h"
#include "Player/AuraPlayerState.h"

/*
 * 发送初始值后，绑定信号槽，在蓝图绑定触发事件更新UI
 */
void UOverlayWidgetController::BroadcastInitialValues()
{
	//Super::BroadcastInitialValues();

	OnMaxHealthChanged.Broadcast(GetAuraAS()->GetMaxHealth());
	OnMaxManaChanged.Broadcast(GetAuraAS()->GetMaxMana());
	OnMaxEnergyChanged.Broadcast(GetAuraAS()->GetMaxEnergy());

	OnHealthChanged.Broadcast(GetAuraAS()->GetHealth());//通过Broadcast方法将当前的生命值广播出去，通知其他相关的系统或组件
	OnManaChanged.Broadcast(GetAuraAS()->GetMana());
	OnEnergyChanged.Broadcast(GetAuraAS()->GetEnergy());
	


}

void UOverlayWidgetController::BindCallbacksToDependencies()
{
	//Super::BindCallbacksToDependencies();

	GetAuraPS()->OnXPChangedDelegate.AddUObject(this, &UOverlayWidgetController::OnXPChanged);
	GetAuraPS()->OnMoneyChangedDelegate.AddUObject(this, &UOverlayWidgetController::OnMoneyChanged);

	//绑定等级相关回调
	GetAuraPS()->OnLevelChangedDelegate.AddLambda([this](int32 NewLevel)
	{
		OnPlayerLevelChangeDelegate.Broadcast(NewLevel);
	});

	
	
	/*
	* 获取AuraAttributeSet中的健康属性值变化委托。
	* 将当前对象的HealthChanged方法绑定到这个委托上，以便在健康属性值发生变化时调用HealthChanged方法。
	 */
	/*匿名函数迭代
	UAuraWidgetController::AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AuraAttributeSet->GetHealthAttribute()).AddUObject(this, &UOverlayWidgetController::HealthChanged);
	*/

	UAuraWidgetController::AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(GetAuraAS()->GetHealthAttribute()).AddLambda(
		[this](const FOnAttributeChangeData& Data)
		{
			OnHealthChanged.Broadcast(Data.NewValue);
		});
	
	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(GetAuraAS()->GetMaxHealthAttribute()).AddLambda(
		[this](const FOnAttributeChangeData& Data)
		{
			OnMaxHealthChanged.Broadcast(Data.NewValue);
		});

	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(GetAuraAS()->GetEnergyAttribute()).AddLambda(
		[this](const FOnAttributeChangeData& Data)
		{
			OnEnergyChanged.Broadcast(Data.NewValue);
		});

	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(GetAuraAS()->GetMaxEnergyAttribute()).AddLambda(
		[this](const FOnAttributeChangeData& Data)
		{
			OnMaxEnergyChanged.Broadcast(Data.NewValue);
		});

	
	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(GetAuraAS()->GetManaAttribute()).AddLambda(
		[this](const FOnAttributeChangeData& Data)
		{
			OnManaChanged.Broadcast(Data.NewValue);
		});

	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(GetAuraAS()->GetMaxManaAttribute()).AddLambda(
		[this](const FOnAttributeChangeData& Data)
		{
			OnMaxManaChanged.Broadcast(Data.NewValue);
		});

	if(GetAuraASC())
	{
		GetAuraASC()->AbilityEquipped.AddUObject(this, &UOverlayWidgetController::OnAbilityEquipped);
		if (GetAuraASC()->bStartupAbilitiesGiven)
		{
			BroadcastAbilityInfo();
		}
		else
		{
			GetAuraASC()->AbilityGivenDelegate.AddUObject(this, &UOverlayWidgetController::BroadcastAbilityInfo);
		}
		
		
		//AddLambda 绑定匿名函数
		GetAuraASC()->EffectAssetTags.AddLambda(
		[this](const FGameplayTagContainer& AssetTags)
		{
			for(const FGameplayTag& Tag : AssetTags)
			{
        
				//对标签进行检测，如果不是信息标签，将无法进行广播
				FGameplayTag MessageTag = FGameplayTag::RequestGameplayTag(FName("Message"));
				//"A.1".MatchesTag（“A”） 将返回 True， “A”.MatchesTag（“A.1”） 将返回 False				
				//Tag如果是Message.某某则返回true
				if(Tag.MatchesTag(MessageTag))
				{
					//将tag广播给Widget Controller
					//测试用途，打印
					//const FString Msg = FString::Printf(TEXT("GE Tag in Widget Controller: %s"), *Tag.ToString()); //获取Asset Tag
					//GEngine->AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, Msg); //打印到屏幕上 -1 不会被覆盖
					const FUIWidgetRow* Row = GetDataTableRowByTag<FUIWidgetRow>(MessageWigetDataTable , Tag);
					MessageWidgetRowDelegate.Broadcast(*Row);
				}
        
			}
		}
		);
		//---
	}
}


void UOverlayWidgetController::OnXPChanged(int32 NewXP) 
{
	const ULeveUpInfo* LevelUpInfo = GetAuraPS()->LevelUpInfo;
	checkf(LevelUpInfo, TEXT("无法查询到等级相关数据，请查看PlayerState是否设置了对应的数据"));

	const int32 Level =  LevelUpInfo->FindLevelForXP(NewXP); //获取当前等级
	const int32 MaxLevel = LevelUpInfo->LevelUpInformation.Num(); //获取当前最大等级

	if(Level <= MaxLevel && Level > 0)
	{

		const int32 LevelUpRequirement = LevelUpInfo->LevelUpInformation[Level].LevelUpRequirement;
		const int32 PreviousLevelUpRequirement = LevelUpInfo->LevelUpInformation[Level - 1].LevelUpRequirement;

		const int32 DeltaLevelRequirement = LevelUpRequirement - PreviousLevelUpRequirement;
		const int32 XPForThisLevel = NewXP - PreviousLevelUpRequirement;

		const float XPBarPercent = static_cast<float>(XPForThisLevel) / static_cast<float>(DeltaLevelRequirement);

		OnXPPercentChangedDelegate.Broadcast(XPBarPercent);
	}

}

void UOverlayWidgetController::OnMoneyChanged(int32 NewMoney)
{
	OnPlayerMoneyChangeDelegate.Broadcast(NewMoney);
	
}

void UOverlayWidgetController::OnAbilityEquipped(
	const FGameplayTag& AbilityTag, const FGameplayTag& Status, const FGameplayTag& Slot,
	const FGameplayTag& PreviousSlot
) const
{
	const FAuraGameplayTags GameplayTags = FAuraGameplayTags::Get();

	//清除旧插槽的数据
	FAuraAbilityInfo LastSlotInfo;
	LastSlotInfo.StatusTag = GameplayTags.Abilities_Status_Unlocked;
	LastSlotInfo.InputTag = PreviousSlot;
	LastSlotInfo.AbilityTag = GameplayTags.Abilities_None;
	AbilityInfoDelegate.Broadcast(LastSlotInfo);

	//更新新插槽的数据
	FAuraAbilityInfo Info = AbilityInfo->FindAbilityInfoForTag(AbilityTag);
	Info.StatusTag = Status;
	Info.InputTag = Slot;
	AbilityInfoDelegate.Broadcast(Info);
	
}
